package com.tywj.lib.lifecycle.livedata

/**
 * <pre>
 *     author : June Yang
 *     time   : 2020/5/13
 *     desc   : 可观察数组集合元素变化的LiveData
 *     version: 1.0.0
 * </pre>
 */
class ArrayListLiveData<T> : SingleLiveEvent<ListChanged>() {

    val rawList = ArrayList<T>()

    fun add(element: T): Boolean {
        val result = rawList.add(element)
        if (result) {
            val changed = ListChanged(ListChanged.TYPE_ITEM_RANGE_INSERTED)
            changed.positionStart = rawList.size - 1
            changed.itemCount = 1
            postValue(changed)
            return true
        } else {
            return false
        }
    }

    fun add(index: Int, element: T) {
        rawList.add(index, element)
        val changed = ListChanged(ListChanged.TYPE_ITEM_RANGE_INSERTED)
        changed.positionStart = index
        changed.itemCount = 1
        postValue(changed)
    }

    fun addAll(elements: Collection<T>): Boolean {
        val oldSize = rawList.size
        val added = rawList.addAll(elements)
        if (added) {
            val changed = ListChanged(ListChanged.TYPE_ITEM_RANGE_INSERTED)
            changed.positionStart = oldSize
            changed.itemCount = rawList.size - oldSize
            postValue(changed)
            return true
        } else {
            return false
        }
    }

    fun addAll(index: Int, elements: Collection<T>): Boolean {
        val added = rawList.addAll(index, elements)
        if (added) {
            val changed = ListChanged(ListChanged.TYPE_ITEM_RANGE_INSERTED)
            changed.positionStart = index
            changed.itemCount = elements.size
            postValue(changed)
            return true
        } else {
            return false
        }
    }

    fun clear() {
        val oldSize = rawList.size
        if (oldSize > 0) {
            rawList.clear()
            val changed = ListChanged(ListChanged.TYPE_ITEM_RANGE_REMOVED)
            changed.positionStart = 0
            changed.itemCount = oldSize
            postValue(changed)
        }
    }

    fun remove(element: T): Boolean {
        val index = rawList.indexOf(element)
        if (index >= 0) {
            removeAt(index)
            return true
        } else {
            return false
        }
    }

    fun removeAt(index: Int): T {
        val element = rawList.removeAt(index)
        val changed = ListChanged(ListChanged.TYPE_ITEM_RANGE_REMOVED)
        changed.positionStart = index
        changed.itemCount = 1
        postValue(changed)
        return element
    }

    fun set(index: Int, element: T): T {
        val oldValue = rawList.set(index, element)
        val changed = ListChanged(ListChanged.TYPE_ITEM_RANGE_CHANGED)
        changed.positionStart = index
        changed.itemCount = 1
        postValue(changed)
        return oldValue
    }

    fun setNewList(elements: Collection<T>): Boolean {
        rawList.clear()
        val added = rawList.addAll(elements)
        if (added) {
            val changed = ListChanged(ListChanged.TYPE_CHANGED)
            postValue(changed)
            return true
        } else {
            return false
        }
    }

    fun move(fromPosition: Int, toPosition: Int) {
        val fromElement = rawList[fromPosition]
        val toElement = rawList[toPosition]
        rawList[fromPosition] = toElement
        rawList[toPosition] = fromElement

        val changed = ListChanged(ListChanged.TYPE_ITEM_MOVE)
        changed.fromPosition = fromPosition
        changed.toPosition = toPosition
        postValue(changed)
    }

    operator fun get(position: Int): T = this.rawList[position]
}